package com.tom.demo.service.common.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.tom.demo.common.entity.CpTempFileBaseInfo;
import com.tom.demo.service.common.AnalyzeSplitGenerateService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;


@Slf4j
@Service
public class AnalyzeSplitGenerateServiceImpl implements AnalyzeSplitGenerateService {

    @Resource
    private MinioClient minioClient;

    @Value("${bucketName}")
    private String minioBucket;

    @Value("${temp.dir}")
    private String tempDir;

    private static final Set<String> ALLOWED_EXTENSIONS = new HashSet<>(
            Arrays.asList("pdf", "xls", "xlsx", "csv", "zip"));

    /**
     * 文件上传接口
     * @param files 上传的文件数组
     * @return 处理结果列表
     */
    @Override
    public List<CpTempFileBaseInfo> analyzeSplitGenerateService(MultipartFile[] files, HttpServletRequest httpServletRequest) {
        // 结果列表
        List<CpTempFileBaseInfo> results = new ArrayList<>();

        for (MultipartFile file : files) {
            try {
                if (file.isEmpty()) {
                    continue;
                }

                String originalFilename = file.getOriginalFilename();
                if (originalFilename == null || originalFilename.isEmpty()) {
                    continue;
                }

                String extension = FilenameUtils.getExtension(originalFilename).toLowerCase();

                if (!ALLOWED_EXTENSIONS.contains(extension)) {
                    CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                    failInfo.setFileName(originalFilename);
                    failInfo.setParseStatus(1);
                    failInfo.setFailReason("不支持的文件格式: " + extension);
                    results.add(failInfo);
                    continue;
                }

                CpTempFileBaseInfo fileInfo = new CpTempFileBaseInfo();
                fileInfo.setFileName(originalFilename);
                fileInfo.setFundId(123);
                fileInfo.setFundCode("PF123456");
                fileInfo.setCustodyReview("4");

                processFile(file, fileInfo, results);

            } catch (Exception e) {
                log.error(e.getMessage(), e);
                CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                failInfo.setFileName(file.getOriginalFilename());
                failInfo.setParseStatus(1);
                failInfo.setFailReason("处理文件时发生错误: " + e.getMessage());
                results.add(failInfo);
            }
        }
        return results;
    }


    /**
     * 处理单个文件
     * @param file 文件对象
     * @param fileInfo 文件信息对象
     * @param results 结果列表
     * @throws Exception 处理异常
     */
    private void processFile(MultipartFile file, CpTempFileBaseInfo fileInfo, List<CpTempFileBaseInfo> results)
            throws Exception {
        String originalFilename = file.getOriginalFilename();
        String extension = Objects.requireNonNull(FilenameUtils.getExtension(originalFilename)).toLowerCase();
        fileInfo.setFileType(getFileTypeCode(extension));

        // 直接上传的文件,设置dataRoute为null
        fileInfo.setDataRoute(null);

        if ("zip".equalsIgnoreCase(extension)) {
            // 处理ZIP文件 - 传递ZIP文件名作为顶级路径
            processZipFile(file, fileInfo.getFundId(), fileInfo.getFundCode(), fileInfo.getCustodyReview(),
                    FilenameUtils.getBaseName(originalFilename), results);
        } else if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
            // 处理Excel文件的每个工作表
            processExcelSheets(file.getInputStream(), fileInfo, results);
        } else if ("csv".equalsIgnoreCase(extension)) {
            // 处理CSV文件
            processCsvFile(file.getInputStream(), fileInfo, results);
        } else if ("pdf".equalsIgnoreCase(extension)) {
            // PDF直接上传到MinIO
            String objectName = generateUniqueObjectName(file.getOriginalFilename());
            uploadToMinio(file.getInputStream(), objectName, file.getContentType(), file.getSize());
            fileInfo.setFilePath(getMinioFilePath(objectName));
            fileInfo.setParseStatus(0); // 成功
            results.add(fileInfo);
        }
    }

    /**
     * 处理ZIP文件
     * @param file 文件对象
     * @param fundId 基金ID
     * @param fundCode 基金代码
     * @param custodyReview 托管复核标识
     * @param zipBaseName ZIP文件基本名称
     * @param results 结果列表
     * @throws Exception 处理异常
     */
    private void processZipFile(MultipartFile file, Integer fundId, String fundCode,
                                String custodyReview, String zipBaseName, List<CpTempFileBaseInfo> results) throws Exception {
        // 创建临时目录
        Path tempPath = Paths.get(tempDir, IdUtil.simpleUUID());
        Files.createDirectories(tempPath);
        try {
            // 解压ZIP文件 - 传递ZIP基本名称
            extractZipFile(file.getInputStream(), tempPath, zipBaseName, fundId, fundCode, custodyReview, results);
        } catch (Exception e) {
            CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
            failInfo.setFileName(file.getOriginalFilename());
            failInfo.setParseStatus(1);
            failInfo.setFailReason("ZIP文件格式错误: " + e.getMessage());
            results.add(failInfo);
            log.error("zip文件解压异常,{}", e.getMessage());
        } finally {
            // 删除临时目录和文件
            deleteDirectory(tempPath.toFile());
        }
    }

    /**
     * 解压ZIP文件并处理里面的文件
     */
    private void extractZipFile(InputStream inputStream, Path outputPath,String zipBaseName,
                                Integer fundId, String fundCode, String custodyReview,
                                List<CpTempFileBaseInfo> results) throws Exception {
        extractZipFileWithDepth(inputStream, outputPath, zipBaseName, fundId, fundCode,
                custodyReview, results, CharsetUtil.CHARSET_GBK, 0);
    }

    /**
     * 带递归深度控制的ZIP解压方法
     */
    private void extractZipFileWithDepth(InputStream inputStream, Path outputPath, String zipBaseName,
                                         Integer fundId, String fundCode, String custodyReview,
                                         List<CpTempFileBaseInfo> results, Charset charset, int depth) throws Exception {
        // 限制最大递归深度
        final int MAX_DEPTH = 10;
        if (depth > MAX_DEPTH) {
            CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
            failInfo.setFileName(zipBaseName);
            failInfo.setDataRoute(zipBaseName);
            failInfo.setParseStatus(1);
            failInfo.setFailReason("ZIP嵌套层级过深，超过最大限制" + MAX_DEPTH + "层");
            results.add(failInfo);
            return;
        }

        // 为当前ZIP创建唯一子目录，避免重复处理相同文件
        String uniqueSubDir = UUID.randomUUID().toString();
        Path zipOutputPath = outputPath.resolve(uniqueSubDir);
        Files.createDirectories(zipOutputPath);

        // 创建临时文件用于解压
        File tempZipFile = FileUtil.createTempFile("temp_zip", ".zip", true);
        try {
            // 将输入流写入临时文件
            FileUtil.writeFromStream(inputStream, tempZipFile);

            // 尝试自动检测编码或使用传入的编码进行解压
            boolean success = false;
            Exception lastException = null;

            // 尝试使用传入的编码
            try {
                ZipUtil.unzip(tempZipFile, zipOutputPath.toFile(), charset);
                success = true;
            } catch (Exception e) {
                lastException = e;
                log.error("使用指定编码{}解压失败，尝试其他编码", charset, e);
            }

            // 如果失败，尝试其他常用编码
            if (!success) {
                Charset[] charsets = new Charset[]{
                        CharsetUtil.CHARSET_UTF_8,
                        CharsetUtil.CHARSET_GBK,
                        CharsetUtil.CHARSET_ISO_8859_1
                };

                for (Charset cs : charsets) {
                    if (cs.equals(charset)) continue; // 跳过已尝试的编码

                    try {
                        ZipUtil.unzip(tempZipFile, zipOutputPath.toFile(), cs);
                        log.error("成功使用{}编码解压文件", cs);
                        success = true;
                        charset = cs; // 更新当前成功的编码，用于递归处理
                        break;
                    } catch (Exception e) {
                        log.error("尝试使用{}编码解压失败", cs, e);
                    }
                }
            }

            // 如果所有编码都失败，抛出异常
            if (!success) {
                throw new Exception("无法解压ZIP文件，尝试了多种编码都失败", lastException);
            }

            // 递归处理解压后的文件，传递深度参数
            processExtractedFilesWithDepth(zipOutputPath.toFile(), outputPath, zipBaseName,
                    fundId, fundCode, custodyReview, results, charset, depth);
        } finally {
            // 删除临时文件
            FileUtil.del(tempZipFile);
        }
    }

    /**
     * 带递归深度控制的文件处理方法
     */
    private void processExtractedFilesWithDepth(File directory, Path outputPath, String zipBaseName,
                                                Integer fundId, String fundCode, String custodyReview,
                                                List<CpTempFileBaseInfo> results, Charset charset, int depth) throws Exception {
        File[] files = directory.listFiles();
        if (files == null) return;

        for (File file : files) {
            String fileName = file.getName();
            // 构建当前文件的相对路径
            // 如果是顶层ZIP中的文件，格式应该是: "zipFileName/fileName"
            // 如果是嵌套ZIP中的文件，格式应该是: "zipFileName/nestedZipFileName/fileName"
            String currentRelativePath;
            if (StrUtil.isEmpty(zipBaseName)) {
                // 如果是顶层直接上传的ZIP文件，只用文件名作为路径起点
                currentRelativePath = fileName;
            } else {
                // 如果已经有路径（嵌套ZIP的情况），追加当前文件名
                currentRelativePath = zipBaseName + "/" + fileName;
            }

            if (file.isDirectory()) {
                // 递归处理子目录，保持相同深度
                processExtractedFilesWithDepth(file, outputPath, currentRelativePath,
                        fundId, fundCode, custodyReview, results, charset, depth);
            } else {
                // 处理文件
                String fileExtension = FileUtil.extName(fileName).toLowerCase();
                Path filePath = file.toPath();

                if ("zip".equalsIgnoreCase(fileExtension)) {
                    // 递归处理ZIP文件，增加深度
                    try (InputStream fileIn = Files.newInputStream(filePath)) {
                        extractZipFileWithDepth(fileIn, outputPath, currentRelativePath,
                                fundId, fundCode, custodyReview, results, charset, depth + 1);
                    }
                } else if (ALLOWED_EXTENSIONS.contains(fileExtension)) {
                    // 处理有效文件 - 保持原代码不变
                    CpTempFileBaseInfo fileInfo = new CpTempFileBaseInfo();
                    fileInfo.setFileName(fileName);
                    fileInfo.setFundId(fundId);
                    fileInfo.setFundCode(fundCode);
                    fileInfo.setCustodyReview(custodyReview);
                    // 设置正确的dataRoute - 反映文件在ZIP结构中的位置
                    fileInfo.setDataRoute(currentRelativePath);
                    fileInfo.setFileType(getFileTypeCode(fileExtension));

                    try (InputStream ignored = Files.newInputStream(filePath)) {
                        if ("xls".equalsIgnoreCase(fileExtension) || "xlsx".equalsIgnoreCase(fileExtension)) {
                            processExcelSheets(Files.newInputStream(filePath), fileInfo, results);
                        } else if ("csv".equalsIgnoreCase(fileExtension)) {
                            processCsvFile(Files.newInputStream(filePath), fileInfo, results);
                        } else if ("pdf".equalsIgnoreCase(fileExtension)) {
                            String objectName = generateUniqueObjectName(fileInfo.getFileName());
                            uploadToMinio(Files.newInputStream(filePath), objectName,
                                    getContentType(fileExtension), Files.size(filePath));
                            fileInfo.setFilePath(getMinioFilePath(objectName));
                            fileInfo.setParseStatus(0); // 成功
                            results.add(fileInfo);
                        }
                    }
                } else {
                    // 不支持的文件格式
                    CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                    failInfo.setFileName(fileName);
                    failInfo.setDataRoute(currentRelativePath);
                    failInfo.setParseStatus(1);
                    failInfo.setFailReason("不支持的文件格式: " + fileExtension);
                    results.add(failInfo);
                }
            }
        }

        // 处理完成后删除临时目录
        FileUtil.del(directory);
    }



    /**
     * 处理Excel文件的每个工作表
     * @param inputStream 文件输入流
     * @param baseFileInfo 基础文件信息
     * @param results 结果列表
     * @throws IOException IO异常
     */
    private void processExcelSheets(InputStream inputStream, CpTempFileBaseInfo baseFileInfo,
                                    List<CpTempFileBaseInfo> results) throws IOException {
        // 创建临时文件，用于后续处理
        Path tempExcelPath = Files.createTempFile("excel_", ".xlsx");
        Files.copy(inputStream, tempExcelPath, StandardCopyOption.REPLACE_EXISTING);

        try (Workbook workbook = WorkbookFactory.create(Files.newInputStream(tempExcelPath))) {
            boolean foundAnyContent = false;

            // 遍历所有sheet页
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Sheet sheet = workbook.getSheetAt(i);
                String sheetName = sheet.getSheetName();

                // 检查sheet是否有内容
                boolean hasContent = checkSheetContent(sheet);

                if (hasContent) {
                    foundAnyContent = true;

                    // 为每个有内容的sheet创建单独的fileInfo和文件
                    CpTempFileBaseInfo sheetFileInfo = new CpTempFileBaseInfo();
                    sheetFileInfo.setFundId(baseFileInfo.getFundId());
                    sheetFileInfo.setFundCode(baseFileInfo.getFundCode());
                    sheetFileInfo.setCustodyReview(baseFileInfo.getCustodyReview());
                    sheetFileInfo.setFileType(baseFileInfo.getFileType());
                    sheetFileInfo.setDataRoute(baseFileInfo.getDataRoute());

                    // 修改文件名以包含sheet信息
                    String originalFilename = baseFileInfo.getFileName();
                    String nameWithoutExt = FilenameUtils.removeExtension(originalFilename);
                    String extension = FilenameUtils.getExtension(originalFilename);
                    //String newFileName = nameWithoutExt + "第" + (i + 1) + "页." + extension;
                    String newFileName = nameWithoutExt + "_" + sheetName + "." + extension;
                    log.info("生成的单sheet文件名称是:{}", newFileName);
                    sheetFileInfo.setFileName(newFileName);

                    // 创建只包含当前sheet的新workbook
                    Workbook singleSheetWorkbook;
                    if (workbook instanceof XSSFWorkbook) {
                        singleSheetWorkbook = new XSSFWorkbook();
                    } else {
                        singleSheetWorkbook = new HSSFWorkbook();
                    }

                    Sheet newSheet = singleSheetWorkbook.createSheet(sheetName);

                    // 复制原始sheet内容到新sheet
                    copySheet(sheet, newSheet);

                    // 将单sheet的workbook写入临时文件
                    Path tempSheetPath = Files.createTempFile("sheet_", "." + extension);
                    try (FileOutputStream out = new FileOutputStream(tempSheetPath.toFile())) {
                        singleSheetWorkbook.write(out);
                    }
                    singleSheetWorkbook.close();

                    // 上传单sheet文件到MinIO
                    String objectName = generateUniqueObjectName(newFileName);
                    try (InputStream sheetInputStream = Files.newInputStream(tempSheetPath)) {
                        uploadToMinio(sheetInputStream, objectName,
                                getContentType(extension), Files.size(tempSheetPath));
                    } catch (Exception e) {
                        log.error("上传单sheet文件到MinIO出错,message:{}",e.getMessage(),e);
                        throw new RuntimeException(e);
                    }

                    // 设置文件路径并添加到结果
                    sheetFileInfo.setFilePath(getMinioFilePath(objectName));
                    sheetFileInfo.setParseStatus(0); // 成功
                    results.add(sheetFileInfo);

                    // 删除临时sheet文件
                    Files.deleteIfExists(tempSheetPath);
                }
            }

            // 如果所有sheet都没有内容，添加一个失败记录
            if (!foundAnyContent) {
                baseFileInfo.setParseStatus(1); // 失败
                baseFileInfo.setFailReason("Excel文件的所有sheet页都没有内容");
                results.add(baseFileInfo);
            }
        }catch (Exception e){
            baseFileInfo.setParseStatus(1);
            baseFileInfo.setFailReason("excel文件损坏，无法读取");
            results.add(baseFileInfo);
        }finally {
            // 删除临时Excel文件
            Files.deleteIfExists(tempExcelPath);
        }
    }

    /**
     * 复制sheet内容
     * @param sourceSheet 源sheet
     * @param targetSheet 目标sheet
     */
    private void copySheet(Sheet sourceSheet, Sheet targetSheet) {
        // 复制行
        for (int i = sourceSheet.getFirstRowNum(); i <= sourceSheet.getLastRowNum(); i++) {
            Row sourceRow = sourceSheet.getRow(i);
            if (sourceRow != null) {
                Row targetRow = targetSheet.createRow(i);

                // 复制行高和样式
                targetRow.setHeight(sourceRow.getHeight());

                // 复制单元格
                for (int j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++) {
                    Cell sourceCell = sourceRow.getCell(j);
                    if (sourceCell != null) {
                        Cell targetCell = targetRow.createCell(j);

                        // 复制单元格内容
                        switch (sourceCell.getCellType()) {
                            case STRING:
                                targetCell.setCellValue(sourceCell.getStringCellValue());
                                break;
                            case NUMERIC:
                                if (DateUtil.isCellDateFormatted(sourceCell)) {
                                    targetCell.setCellValue(sourceCell.getDateCellValue());
                                    // 创建新样式而不是直接克隆
                                    CellStyle dateStyle = targetCell.getSheet().getWorkbook().createCellStyle();
                                    // 复制日期格式
                                    short formatIndex = sourceCell.getCellStyle().getDataFormat();
                                    String formatString = sourceCell.getCellStyle().getDataFormatString();
                                    if (formatString != null) {
                                        dateStyle.setDataFormat(targetCell.getSheet().getWorkbook().createDataFormat().getFormat(formatString));
                                    } else {
                                        dateStyle.setDataFormat(formatIndex);
                                    }
                                    targetCell.setCellStyle(dateStyle);
                                } else {
                                    targetCell.setCellValue(sourceCell.getNumericCellValue());
                                }
                                break;
                            case BOOLEAN:
                                targetCell.setCellValue(sourceCell.getBooleanCellValue());
                                break;
                            case FORMULA:
                                targetCell.setCellFormula(sourceCell.getCellFormula());
                                break;
                            case BLANK:
                                targetCell.setBlank();
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    /**
     * 处理CSV文件
     * @param inputStream 文件输入流
     * @param baseFileInfo 基础文件信息
     * @param results 结果列表
     * @throws IOException IO异常
     */
    private void processCsvFile(InputStream inputStream, CpTempFileBaseInfo baseFileInfo,
                                List<CpTempFileBaseInfo> results) throws Exception {
        // 创建临时文件保存CSV内容
        Path tempCsvPath = Files.createTempFile("csv_", ".csv");
        Files.copy(inputStream, tempCsvPath, StandardCopyOption.REPLACE_EXISTING);

        try {
            // 检查CSV是否有内容
            boolean hasContent = false;

            // 使用更鲁棒的方式读取文件 - 字节流处理
            try (InputStream fis = Files.newInputStream(tempCsvPath);
                 InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.ISO_8859_1); // ISO-8859-1可以读取任何字节
                 BufferedReader reader = new BufferedReader(isr)) {

                String line;
                while ((line = reader.readLine()) != null) {
                    String trimmedLine = line.trim();
                    // 检查行是否包含实际内容（非空字符）
                    if (!trimmedLine.isEmpty()) {
                        // 进一步检查是否只包含分隔符（如逗号）
                        String contentWithoutSeparators = trimmedLine.replace(",", "")
                                .replace(";", "")
                                .replace("|", "")
                                .replace("\t", "");
                        if (!contentWithoutSeparators.isEmpty()) {
                            hasContent = true;
                            break;
                        }
                    }
                }
            }

            if (hasContent) {
                // CSV文件有内容，创建一个单独的记录  CSV不支持多个sheet页
                String originalFilename = baseFileInfo.getFileName();
                String nameWithoutExt = FilenameUtils.removeExtension(originalFilename);
                String extension = FilenameUtils.getExtension(originalFilename);
                String newFileName = nameWithoutExt  + "." + extension;

                // 上传CSV文件到MinIO
                String objectName = generateUniqueObjectName(newFileName);
                try (InputStream csvInputStream = Files.newInputStream(tempCsvPath)) {
                    uploadToMinio(csvInputStream, objectName,
                            getContentType(extension), Files.size(tempCsvPath));
                }

                baseFileInfo.setFileName(newFileName);
                baseFileInfo.setFilePath(getMinioFilePath(objectName));
                baseFileInfo.setParseStatus(0); // 成功
                results.add(baseFileInfo);
            } else {
                // CSV文件没有内容，记录失败
                baseFileInfo.setParseStatus(1); // 失败
                baseFileInfo.setFailReason("CSV文件为空或只包含分隔符");
                results.add(baseFileInfo);
            }
        } catch (Exception e) {
            baseFileInfo.setParseStatus(1); // 失败
            baseFileInfo.setFailReason("解析CSV文件失败: " + e.getMessage());
            results.add(baseFileInfo);
            log.error("解析CSV文件失败,{}", e.getMessage());
        } finally {
            // 删除临时CSV文件
            Files.deleteIfExists(tempCsvPath);
        }
    }

    /**
     * 检查工作表是否有内容
     * @param sheet 工作表对象
     * @return 是否有内容
     */
    private boolean checkSheetContent(Sheet sheet) {
        int firstRow = sheet.getFirstRowNum();
        int lastRow = sheet.getLastRowNum();

        // 检查sheet是否有任何行
        if (lastRow >= firstRow) {  // 这意味着至少有一行
            // 遍历所有行
            for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row != null) {  // 确保行不是null
                    // 遍历行中的所有单元格
                    for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
                        Cell cell = row.getCell(cellIndex);
                        if (cell != null && cell.getCellType() != CellType.BLANK) {
                            String cellValue = getCellValueAsString(cell);
                            if (cellValue != null && !cellValue.trim().isEmpty()) {
                                return true; // 找到了内容
                            }
                        }
                    }
                }
            }
        }

        return false; // 没有找到内容
    }

    /**
     * 获取单元格值为字符串
     * @param cell 单元格对象
     * @return 单元格值字符串
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return cell.getStringCellValue();
                } catch (Exception e) {
                    try {
                        return String.valueOf(cell.getNumericCellValue());
                    } catch (Exception ex) {
                        return cell.getCellFormula();
                    }
                }
            default:
                return "";
        }
    }

    /**
     * 生成唯一的对象名
     * @param originalFilename 原始文件名
     * @return 唯一对象名
     */
    private String generateUniqueObjectName(String originalFilename) {
        String extension = FilenameUtils.getExtension(originalFilename);
        String name = FilenameUtils.getBaseName(originalFilename);
        String fileName = (name.length()>60?name.substring(0,60):name);
        if(StringUtils.hasText(fileName)){
            String pattern = "[^a-zA-Z0-9\\u4e00-\\u9fa5-_.]";
            fileName = fileName.replaceAll(pattern, "");
        }
        return fileName + "_" + IdUtil.simpleUUID() + (extension.isEmpty() ? "" : "." + extension);
    }

    /**
     * 上传文件到MinIO
     * @param inputStream 文件输入流
     * @param objectName 对象名称
     * @param contentType 内容类型
     * @param fileSize 文件大小
     * @throws Exception 上传异常
     */
    private void uploadToMinio(InputStream inputStream, String objectName,
                               String contentType, long fileSize) throws Exception {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(minioBucket)
                        .object(objectName)
                        .stream(inputStream, fileSize, -1)
                        .contentType(contentType)
                        .build());
    }

    /**
     * 获取MinIO文件路径
     * @param objectName 对象名称
     * @return MinIO文件路径
     */
    private String getMinioFilePath(String objectName) {
        return minioBucket + "/" + objectName;
    }

    /**
     * 获取文件类型代码
     * @param extension 文件扩展名
     * @return 文件类型代码
     */
    private String getFileTypeCode(String extension) {
        if ("pdf".equalsIgnoreCase(extension)) {
            return "0";
        } else if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
            return "1";
        } else if ("jpg".equalsIgnoreCase(extension) || "jpeg".equalsIgnoreCase(extension) ||
                "png".equalsIgnoreCase(extension) || "gif".equalsIgnoreCase(extension)) {
            return "2";
        } else if ("csv".equalsIgnoreCase(extension)) {
            return "3";
        } else {
            return "9"; // 其他类型
        }
    }

    /**
     * 获取内容类型
     * @param extension 文件扩展名
     * @return 内容类型
     */
    private String getContentType(String extension) {
        switch (extension.toLowerCase()) {
            case "pdf":
                return "application/pdf";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "csv":
                return "text/csv";
            case "zip":
                return "application/zip";
            default:
                return "application/octet-stream";
        }
    }

    /**
     * 递归删除目录
     * @param directory 要删除的目录
     */
    private void deleteDirectory(File directory) {
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        if(file.delete()){
                            log.info("清理临时文件成功！");
                        }

                    }
                }
            }
            if(directory.delete()){
                log.info("清理临时目录成功！");
            }
        }
    }
}
